#include <stdio.h>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>

#include "queue.h"
#include "mqueue.h"

#define CONSUMERS 200    /* 并发执行的线程数 */
#define MAX_PACKETS 1000 /* 总任务数 */
/* 在这个测试程序里，MAX_PACKETS / CONSUMERS 必须为整数 */
/* 这个要求实际上与多线程队列数据结构无关，可以改成其他调度策略 */

/*
 * 数据包捕获线程（单线程）
 */
void *capture_packet(void *args)
{
    printf("Created capture thread tid=%lu\n", pthread_self());
    int i;
    MQUEUE_T *pstMQueue = (MQUEUE_T *)args;

    for (i = 0; i < MAX_PACKETS; i++)
    {
        char data[16]={'0'};
        snprintf(data, 16, "%d", i);
        enMQueue(pstMQueue, (void *)data, strlen(data)); 
    }

    return NULL;
}

/*
 * 数据包处理线程（可以并发多线程处理）
 */
void *inspect_packet(void *args)
{
    printf("Created thread tid=%lu\n", pthread_self());
    int i;
    MQUEUE_T *pstMQueue = (MQUEUE_T *)args;

    for (i = 0; i < MAX_PACKETS / CONSUMERS; i++)/* 任务分配策略 */
    {
        NODE pstNode = { /* 注意这里实际上并没有使用堆内存，而是直接使用的栈内存 */
            0,
            (void *)0,
            NULL
        };
        if (deMQueue(pstMQueue, &pstNode) == true) /* 取出数据 */
        {
            printf("%d deQueue\n", atoi((char *)(&pstNode)->pcData)); /* 数据处理中... */
        }
        if ((&pstNode)->pcData != NULL) /* 释放pstNode节点中为数据动态分配的内存 */
        {
            free((&pstNode)->pcData);
        }
    }

    return NULL; /* 函数返回时，pstNode结构体会自动销毁 */
}

int main()
{
    pthread_t producers;
    pthread_t consumers[CONSUMERS];

    /* 分配队列指针和内存 */
    MQUEUE_T *pstMQueue = (MQUEUE_T *)malloc(sizeof(MQUEUE_T));
    if (pstMQueue == NULL)
    {
        perror("pstMqueue malloc failed!");
        exit(-1);
    }
    pstMQueue->pstQueue = (QUEUE *)malloc(sizeof(QUEUE));
    if (pstMQueue->pstQueue == NULL)
    {
        perror("pstMqueue->pstQueue malloc failed!");
        exit(-1);
    }
    /* 初始化队列结构体 */
    if (initMQueue(pstMQueue, 10) == false)
    {
        free(pstMQueue->pstQueue);
        free(pstMQueue);
        exit(-1);
    }

    /* 队列数据填充 */
    int i;
    pthread_create(&producers, NULL, capture_packet, pstMQueue);/* 相当于数据包捕获的线程 */

    for (i = 0; i < CONSUMERS; i++)
    {
        pthread_create(&consumers[i], NULL, inspect_packet, pstMQueue); /* 相当于数据包分析的线程 */
    }


    /* 等待子线程运行退出 */
    pthread_join(producers, NULL);

    for (i = 0; i < CONSUMERS; i++)
    {
        pthread_join(consumers[i], NULL);
    }

    /* 销毁队列数据结构 */
    freeMQueue(pstMQueue);

    return 0;
}

